<template>
  <div class="addOrEditKnowledge">
    <el-form class="m7-form clearfix knowledgeForm"
      ref="knowledgeForm" :model="knowledgeForm" :rules="rule"
      label-position="top" size="mini" v-if="importType === 'knowledge_mgt_channel'">
        <el-form-item label="知识名称" prop="title">
          <el-input size="mini" v-model="knowledgeForm.title" placeholder="请输入知识名称"></el-input>
        </el-form-item>
        <el-form-item label="知识位置" prop="validity">
          <el-cascader
            v-model="knowledgeForm.newCatalogId"
            :props="{ checkStrictly: true, value: '_id' }"
            :options="options"
            placeholder="默认选择当前目录"
            clearable
            filterable>
          </el-cascader>
          <div v-if="knowledgeForm._id" class="validity">
            <el-radio v-model="knowledgeForm.type" label="mv">移动到该目录</el-radio>
            <el-radio v-model="knowledgeForm.type" label="cp">复制到该目录</el-radio>
          </div>
        </el-form-item>
        <el-form-item label="知识库有效期" prop="validityPeriodType">
          <m7Select
            size="mini"
            v-model="knowledgeForm.validityPeriodType"
            :options="validityOpt"
            :placeholder="'请选择时效'"
            filterable
            :defaultProps="{ label: 'name', value: '_id' }"
            :multiple="false">
          </m7Select>
          <el-date-picker
            style="width:100%"
            popper-class="validityPeriod"
            v-if="knowledgeForm.validityPeriodType === 'custom'"
            v-model="knowledgeForm.validityPeriod"
            type="datetimerange"
            :clearable="true"
            value-format='yyyy-MM-dd HH:mm:ss'
            :picker-options="pickerOptions"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            align="right">
          </el-date-picker>
        </el-form-item>
    </el-form>
    <el-form class="m7-form clearfix knowledgeForm" style="marginTop:5px"
      ref="knowledgeForm" :model="knowledgeForm" :rules="rule"
      label-position="top" size="mini" v-else>
        <el-form-item label="快捷词" prop="title">
          <span slot="label">
            快捷词
            <el-tooltip class="item" effect="dark" content="在聊天框中通过输入快捷词可引用出本条快捷回复内容，快捷词不会发出" placement="top">
              <span class="V7_iconfont V7_iconV7tubiao_bangzhu-42 tip-span"></span>
            </el-tooltip>
          </span>
          <el-input maxlength="50" size="mini" v-model="knowledgeForm.title" placeholder="请输入快捷词"></el-input>
        </el-form-item>
        <el-form-item label="类别" prop="validity">
          <el-cascader
            v-model="knowledgeForm.newCatalogId"
            :props="{ checkStrictly: true, value: '_id' }"
            :options="options"
            placeholder="默认选择当前目录"
            clearable
            filterable>
          </el-cascader>
        </el-form-item>
    </el-form>
    <div class="title">{{importType === 'knowledge_mgt_channel' ? '知识库内容' : '常用语内容'}}</div>
    <div v-if="importType === 'knowledge_mgt_channel'">
      <div id="editor"></div>
      <el-upload
        class="upLoad"
        :show-file-list="false"
        accept=".jpg, .gif, .png, .bmp .txt, .xlsx, .xls, .docx, .doc, .pdf, .ppt, .pptx, .key, .mp3, .wave, .mpeg, .midi, .mp4"
        action=""
        :on-success="uploadSuccess"
        :on-error="uploadError"
        :onProgress="onFileProgress"
        :before-upload="beforeUpload"
        :http-request="uploadRequest">
        <div class="addAttachs">
          <i class="addBtn V7_iconV7tubiao_fujian V7_iconfont" style="padding-right:4px;font-size:12px"></i><span class="addBtn">添加附件</span><span class="size">（大小不超过50M）</span>
        </div>
      </el-upload>
      <div style="marginTop: 20px">
        <div class="attachsItem" v-for="(item, index) in attachsObj" :key="index">
          <a :href="doMain + item.filePath" target="_blank" download>{{item.fileName}}</a>
          <span class="attachDel" @click="attachDelFun(item, index)"><i style="font-size:12px" class="V7_iconfont V7_iconV7tubiao_guanbi"></i></span>
          <span title="预览" v-preview.delete="[item.fileName, doMain + item.filePath]"><i style="font-size:14px;margin-left:8px;cursor:pointer" class="V7_iconfont V7_iconV7tubiao_kejian"></i></span>
        </div>
      </div>
      <el-progress v-if="isShowProgress" :text-inside="true" :stroke-width="24" :percentage="progress" status="success"></el-progress>
    </div>
    <div v-else>
      <el-input show-word-limit maxlength="400" type="textarea" size="mini" v-model="content" placeholder="请输入常用语内容"></el-input>
    </div>
    <div class="fr btn">
      <el-button size="mini" @click="cancelFun">取消</el-button>
      <el-button type="primary" size="mini" @click="saveFun">保存</el-button>
    </div>
    <div v-if="previewImgShow" class="previewMask">
      <img
        :src="previewSrc"
        alt=""
        width="50%"
        height="auto"
        @mousewheel.prevent="scaleFun"
        :style="scaleImgStyle"
        ref="previewImg"
      >
    </div>
  </div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'
import { deepClone } from '@/utils/common'
import { uploadQiniu } from '@/utils/upload'
import WangEditor from 'wangeditor'
import { KmModule } from '@/store/modules/km/index'
@Component({
  name: 'addOrEditKnowledge'
})
export default class AddOrEditKnowledge extends Vue {
  private $message: any
  private $bus: any
  private $route: any
  private $store: any

  private doMain = ''

  private editor: any = null

  private fileName = ''

  private content = ''

  private isShowProgress: boolean = false

  private progress = 0

  private attachsObj: any = []

  private knowledgeForm: any = {
    title: '',
    catalogId: '',
    type: 'mv',
    newCatalogId: '',
    validityPeriodType: 'permanent',
    validityPeriod: []
  }

  private previewSrc: string = '' // 预览图片的地址

  private previewImgShow: boolean = false // 控制预览图片展示的开关

  private clickImgNum: number = 0 // 点击图片的次数

  private firstClickTime: string = '' // 第一次点击图片的时间

  private clickTime: string = '' // 每次点击图片的时间

  private imgScale: number = 1 // 图片放大倍数

  get importType () {
    return this.$route.path.split('/')[3]
  }

  get scaleImgStyle () {
    return `transform:scale(${this.imgScale})`
  }

  private pickerOptions: any = { // 日期时间的快捷搜索项（最近一周，最近一个月，最近三个月）
    shortcuts: [{
      text: '最近一周',
      onClick (picker) {
        const end = new Date()
        const start = new Date()
        start.setTime(start.getTime() - 3600 * 1000 * 24 * 6)
        const startTime = new Date(start.getFullYear(), start.getMonth(), start.getDate(), 0, 0, 0)
        const endTime = new Date(end.getFullYear(), end.getMonth(), end.getDate(), 23, 59, 59)
        picker.$emit('pick', [startTime, endTime])
      }
    }, {
      text: '最近一个月',
      onClick (picker) {
        const end = new Date()
        const start = new Date()
        start.setTime(start.getTime() - 3600 * 1000 * 24 * 29)
        const startTime = new Date(start.getFullYear(), start.getMonth(), start.getDate(), 0, 0, 0)
        const endTime = new Date(end.getFullYear(), end.getMonth(), end.getDate(), 23, 59, 59)
        picker.$emit('pick', [startTime, endTime])
      }
    }, {
      text: '最近三个月',
      onClick (picker) {
        const end = new Date()
        const start = new Date()
        start.setTime(start.getTime() - 3600 * 1000 * 24 * 89)
        const startTime = new Date(start.getFullYear(), start.getMonth(), start.getDate(), 0, 0, 0)
        const endTime = new Date(end.getFullYear(), end.getMonth(), end.getDate(), 23, 59, 59)
        picker.$emit('pick', [startTime, endTime])
      }
    }]
  }

  private rule = {
    title: [{ required: true, trigger: 'blur', message: '请输入名称' }]
  }

  private validityOpt = [
    { name: '永久有效', _id: 'permanent' },
    { name: '无效', _id: 'invalid' },
    { name: '自定义有效期', _id: 'custom' }
  ]

  private options = []

  private createEdit (callBack): void {
    this.editor = new WangEditor('#editor')
    this.editor.config.menus = [
      'head',
      'bold',
      'fontSize',
      'fontName',
      'italic',
      'underline',
      'strikeThrough',
      'indent',
      'lineHeight',
      'foreColor',
      'backColor',
      'link',
      'list',
      'justify',
      'image',
      'table',
      'undo',
      'redo'
    ]
    // 是否全屏
    this.editor.config.showFullScreen = true
    // 高度
    this.editor.config.height = 200
    this.editor.config.zIndex = 10
    this.editor.config.onchange = (newHtml) => {
      if (new RegExp('<table border="0" width="100%" cellpadding="0" cellspacing="0">').test(newHtml)) {
        newHtml = newHtml.replace(/<table border="0" width="100%" cellpadding="0" cellspacing="0">/g, '<table style="width:100%;" cellpadding="2" cellspacing="0" border="1" bordercolor="#ecf0f3">')
      }
      this.content = newHtml
    }
    const initConfig = (this as any).$store.state.common.initConfig
    const doMain = initConfig && initConfig.qiniuDomainMap ? initConfig.qiniuDomainMap.im : ''
    this.editor.config.customUploadImg = (resultFiles, insertImgFn) => { // 粘贴图片时的回调
      resultFiles.forEach(element => { // 循环对粘贴图片执行上传回显功能
        const request = {
          file: element,
          onError: () => '',
          onProgress: () => '',
          onSuccess: (data: any) => {
            if (data.key) {
              insertImgFn(`${doMain}/${data.key}`) // 图片上传到七牛后图片的回显
            } else {
              return false
            }
          }
        }
        uploadQiniu({ type: 'im', fileName: resultFiles[0].name }, request) // 上传图片到七牛
      });
    };
    this.editor.txt.eventHooks.imgClickEvents.push(this.previewImg) // wangeditor中点击图片触发的事件
    // 创建编辑器
    this.editor.create()
    callBack()
  }

  private previewImg (val: any) { // 双击图片预览
    if (this.clickImgNum === 0) { // 双击中第一次点击的时间
      (this as any).firstClickTime = new Date().getTime()
    }

    (this as any).clickTime = new Date().getTime()

    if ((this as any).clickTime - (this as any).firstClickTime <= 500) { // 双击时间间隔<=500ms
      this.clickImgNum++
      if (this.clickImgNum === 2) {
        this.previewSrc = val.selector.currentSrc // 预览图片的地址
        this.previewImgShow = true
        this.clickImgNum = 0 // 初始化点击次数 不进入延时器
      }
    }

    if (this.clickImgNum !== 0) {
      setTimeout(() => { // 双击时间超过500ms初始化点击次数
        this.clickImgNum = 0
      }, 500)
    }
  }

  private scaleFun (e: any) { // 预览图片的缩放
    const direction: string = e.deltaY > 0 ? 'down' : 'up' // 判断鼠标 向上 还是 向下 滚动
    if (direction === 'up') { // 鼠标向上滚动
      if (this.imgScale <= 4) { // 限制图片放大的最大值
        this.imgScale += 0.1 // 图片放大的步距
      }
    } else { // 鼠标向下滚动
      if (this.imgScale > 1) {
        this.imgScale -= 0.1
      }
    }
  }

  private uploadError () {
    this.$message({ message: '附件上传失败，请重新选择附件上传', type: 'error' })
  }

  private beforeUpload (file: any) {
    const fileName = /[^.]+$/.exec(file.name.replace(/\s/g, ''))
    if (fileName && ['js', 'jsp', 'html', 'php', 'asp', 'aspx', 'jspx', 'exe', 'sh', 'py', 'vbs', 'xml', 'htm'].includes(fileName[0])) {
      this.$message({ message: '不支持上传.js、.jsp、.html、.php、.asp、.aspx、.jspx、.exe、.sh、.py、.vbs、.xml、.htm格式文件', type: 'error' })
      return false
    }
    if (this.attachsObj.length > 10) {
      this.$message.error('最多只允许上传10个附件')
      return false
    }
    if (this.isShowProgress) {
      this.$message.error('当前正有附件上传请稍后再试')
      return false
    }
    this.fileName = file.name.replace(/\s/g, '')
    if (file.size / 1024 / 1024 > 50) {
      this.$message({ message: '附件大小不能超过50M', type: 'error' })
      return false
    } else {
      this.isShowProgress = true
    }
  }

  private attachDelFun (item: any, index: number) {
    const attachsArr = deepClone(this.attachsObj)
    attachsArr.splice(index, 1)
    const actionData = {
      url: '/im-km/action/item/deleteAttach',
      method: 'POST',
      data: {
        kmType: 'inner',
        delAttachs: [item],
        attachs: attachsArr,
        itemId: this.knowledgeForm._id || ''
      }
    }
    KmModule.KmCommonAction(actionData).then(res => {
      if (res && res.success) {
        this.attachsObj.splice(index, 1)
      }
    })
  }

  private uploadRequest (request: any) { // 七牛上传
    uploadQiniu({ type: 'im', fileName: this.fileName }, request)
  }

  private onFileProgress (data: any) {
    this.progress = Math.ceil(data.percent)
  }

  private uploadSuccess (data: any) {
    this.attachsObj.push({ filePath: data.key ? `/${data.key}` : '', fileName: this.fileName })
    this.isShowProgress = false
    this.progress = 0
  }

  private saveFun () {
    const knowledgeFormRef: any = this.$refs.knowledgeForm
    knowledgeFormRef.validate((valid) => {
      if (valid) {
        if (!this.content) {
          this.$message.error('内容不能为空')
        } else {
          let { title, validityPeriodType, _id, type, validityPeriod, catalogId } = this.knowledgeForm
          let sendData: any = {}
          let url: string = ''
          let successMsg: string = ''
          let newCatalogId = null
          if (this.knowledgeForm.newCatalogId) {
            if (typeof this.knowledgeForm.newCatalogId === 'string') {
              newCatalogId = this.knowledgeForm.newCatalogId
            } else {
              newCatalogId = this.knowledgeForm.newCatalogId[this.knowledgeForm.newCatalogId.length - 1]
            }
          }
          if (!_id) {
            catalogId = newCatalogId || this.$route.params.id // 新增时要有移动的目录，传移动的id否则传当前目录id
            if (catalogId === 'all') {
              this.$message.error('全部类别下请填写类别')
              return false
            }
          }
          if (this.importType === 'knowledge_mgt_channel') { // 知识库
            url = `/im-km/action/item/${_id ? 'update' : 'create'}`
            sendData = {
              attachs: this.attachsObj,
              catalogId,
              title,
              kmType: 'inner',
              validityPeriodType,
              content: this.content,
              validityPeriod
            }
            if (_id) {
              sendData.itemId = _id
              sendData.type = type
              sendData.newCatalogId = newCatalogId
            }
            successMsg = `${_id ? '修改' : '添加'}知识点成功`
          } else { // 常用语
            sendData = {
              title,
              content: this.content,
              categoryId: catalogId
            }
            if (_id) {
              sendData._id = _id
              sendData.categoryId = newCatalogId || catalogId
            }
            url = `/im-km/quick-reply/action/${this.importType === 'personal_language' ? 'agent' : 'common'}/content/${_id ? 'update' : 'create'}`
            successMsg = `${_id ? '修改' : '添加'}常用语成功`
          }
          const actionData = { url, method: 'POST', data: sendData }
          KmModule.KmCommonAction(actionData).then(res => {
            if (res && res.success) {
              this.$message.success(successMsg)
              this.$emit('addOrEditKnowledge')
            }
          })
        }
      }
    })
  }

  private cancelFun () {
    this.$emit('cancelFun')
  }

  private activated () {
    const kmData = { url: '/im-km/action/catalog/list', method: 'POST', data: { kmType: 'inner' } }
    const quickReplyData = {
      url: `/im-km/quick-reply/action/${this.importType === 'personal_language' ? 'agent' : 'common'}/category/list`,
      method: 'post',
      data: { isQuickQuery: false }
    }
    const actionData = this.importType === 'knowledge_mgt_channel' ? kmData : quickReplyData
    KmModule.KmCommonAction(actionData).then(res => {
      if (res && res.success) {
        this.options = res.data.tree || []
      }
    })
    this.createEdit(() => {
      this.$bus.$on('addOrEditKnowledge', (row: any) => {
        if (this.importType === 'knowledge_mgt_channel') {
          const { title, _id, newCatalogId, validityPeriodType, content, validityPeriod, attachs, catalogId } = row
          this.editor.txt.html(content)
          this.knowledgeForm = {
            title,
            _id,
            catalogId,
            newCatalogId,
            validityPeriodType,
            validityPeriod,
            type: 'mv'
          }
          this.attachsObj = attachs
        } else {
          const { title, _id, categoryId, content } = row
          this.knowledgeForm = {
            title,
            _id,
            catalogId: categoryId,
            newCatalogId: categoryId
          }
          this.content = content
        }
      })
      this.$bus.$on('addKnowledge', () => {
        if (this.importType === 'knowledge_mgt_channel') {
          this.knowledgeForm = {
            title: '',
            newCatalogId: '',
            catalogId: '',
            validityPeriodType: 'permanent',
            validityPeriod: [],
            type: 'mv'
          }
          this.content = ''
          this.editor.txt.html('')
          this.attachsObj = []
        } else {
          this.knowledgeForm = {
            title: '',
            newCatalogId: '',
            catalogId: ''
          }
          this.content = ''
        }
      })
    })
    const initConfig = this.$store.state.common.initConfig
    const doMain = initConfig && initConfig.qiniuDomainMap ? initConfig.qiniuDomainMap.im : '' // 获取当前上传域名
    this.doMain = doMain + '/'
  }

  private closeMask (e: any) { // 点击非图片区域取消图片预览
    const ref: any = this.$refs.previewImg
    if (ref && !ref.contains(e.target)) {
      this.previewImgShow = false
    }
  }

  private mounted () {
    document.addEventListener('click', this.closeMask)
  }

  private beforeDestroy () {
    document.removeEventListener('click', this.closeMask)
  }

  private deactivated () {
    // // 销毁编辑器
    if (this.editor) {
      this.editor.destroy()
      this.editor = null
    }
    this.$bus.$off('addKnowledge')
    this.$bus.$off('addOrEditKnowledge')
  }
}
</script>
<style lang="stylus" scoped>
  .addOrEditKnowledge
    margin-top 10px
    height calc(100% - 60px)
    overflow auto
    padding-right 10px
    .validity
      margin-top 10px
    .el-cascader
      width 100%
    .el-date-editor
      margin-top 10px
    .knowledgeForm
      width 100%
    >>>.el-form-item
      width 44%
      float left
      height 60px
      margin-right 40px
    .addAttachs
      padding 8px 12px
      border 1px solid #E7E9ED
      border-radius 4px
      .addBtn
        color #008BEE
      .size
        color #767E91
    .attachsItem
      padding 8px 9px
      background #F1F8FD
      border-radius 4px
      color #008BEE
      display inline-block
      margin 0px 10px 10px 0px
      .attachDel
        margin-left 10px
        cursor pointer
  #editor
    margin-bottom 10px
  .btn
    margin-top 20px
  .title
    margin-bottom 10px
  .V7_iconfont
    cursor pointer
  .tip-span
    color #B3B9C7
    font-size 12px
  >>>.w-e-text img
    position relative
    z-index 2
  .previewMask
    position fixed
    top 0
    left 0
    right 0
    bottom 0
    background-color rgba(0, 0, 0, .5)
    z-index 999
    display flex
    justify-content: center
    align-items: center
</style>
